package com.he.utils;

import com.he.entity.Book;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class StreamUtil {

    public static void main(String[] args) {
        //region Map遍历
/*        Map<Integer, String> map = new HashMap<>();
        map.put(1, "huhu");
        map.put(2, "haha");
        map.put(3, "hehe");
        map.forEach((key, value) -> {
            System.out.println("key=" + key + ",value=" + value);
        });*/
        //endregion

        //region    filter 筛选
        /****************************************filter 筛选 *******************************/
//        List<String> list = new ArrayList<>();
//        Collections.addAll(list, "张一", "张二", "张三", "张三丰", "李四");
        //终结方法：foreach
//        list.stream().filter(name -> name.startsWith("张") && name.length() == 3).forEach(System.out::println);
        //endregion

        //region    map 与 peek
        /****************************************map 与 peek, 复制对象到新对象*******************************/
        List<Book> bookList = Arrays.asList(
                new Book(1L, "三国", "军事", 99.5, 0, LocalDateTime.now(), LocalDateTime.now(),1),
                new Book(1L, "水浒", "武侠", 20.8, 0, LocalDateTime.now(), LocalDateTime.now(),1),
                new Book(1L, "西游记", "神话", 111.5, 0, LocalDateTime.now(), LocalDateTime.now(),1));
//        List<Target> targetList = bookList.stream().map(book -> {
//                    Target target = new Target();
//                    BeanUtils.copyProperties(book, target);
//                    target.setWriter("作者");
//                    return target;
//                }
//        ).collect(Collectors.toList());
//        targetList.forEach(System.out::println);
        // 只做调试使用，新创建的Target对象并没有被加入到任何集合中，也没有被用于流中的进一步操作。因此，collect(Collectors.toList())最终收集的还是原始的Book对象列表
//        List<Book> targetList = bookList.stream()
//                .peek(book -> {
//            Target target = new Target();
//            BeanUtils.copyProperties(book, target);
//            target.setWriter("作者");
//        }).collect(Collectors.toList());
        //endregion

        //region flatMap(降维)，如二位数组转为一维
        /****************************************flatMap(降维)，如二位数组转为一维*******************************/
/*        List<String> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        Collections.addAll(list1, "张一", "张二", "张三", "张三丰", "李四");
        Collections.addAll(list2, "苹果","西瓜");
        Stream.of(list1,list2)
                .flatMap(list -> list.stream())
                .forEach(System.out::println);


        Integer[][] array2D = {
                {1, 2, 3},
                {4, 5, 6},
                {7, 8, 9}
        };
        Arrays.stream(array2D).flatMap(array -> Arrays.stream(array)).forEach(System.out::println);*/
        //endregion

        //region    合并与截取
//        Stream<Integer> stream1 = Stream.of(1, 2, 3);
//        Stream<Integer> stream2 = Stream.of(4, 5);
//
//        //合并
//        Stream<Integer> concat = Stream.concat(stream1, stream2);
//        concat.forEach(System.out::println);

        /**
         * 截取
         * 1、根据位置截取
         *      skip：跳过N个数据，保留剩下的数据；
         *      limit：保留N个数据，剩下的不要
         * 2、根据条件截取     jdk1.8没有
         *      takeWhile：条件成立保留，不成立剩下的不要
         *      dropWhile：条件成立不保留，不成立保留剩下的
         */

//        concat.skip(2).forEach(System.out::println);
//        concat.limit(2).forEach(System.out::println);
//        concat.skip(2).limit(2).forEach(System.out::println);
        //endregion

        //region    Stream生成
//        IntStream.range(1,10).forEach(System.out::print);//左闭右开
//        System.out.println();
//        IntStream.rangeClosed(1,10).forEach(System.out::print);//左闭右闭
//        System.out.println();
//
//        //可以根据上一个元素值生成
//        IntStream.iterate(1, x -> x + 2).limit(10).forEach(System.out::print);
////        IntStream.iterate(1, x -> x <= 9, x -> x + 2).forEach(System.out::println); //JDK8不支持
//        System.out.println();
//
//        IntStream.generate(()-> ThreadLocalRandom.current().nextInt(100)).limit(5).forEach(System.out::println);
//        ThreadLocalRandom.current().ints(5,0,100).forEach(System.out::println);

//        List<String> list = new ArrayList<>();
//        Collections.addAll(list, "张一", "张二", "张三", "张三丰", "李四");
//        list.forEach(o ->
//                {
//                    if (o.equals("张三")) {
//                        System.out.println("o = " + o);
//                    }
//                }
//        );
        //endregion

        //region    查找与判断
//        IntStream intStream = IntStream.rangeClosed(1, 10);
//        System.out.println(intStream.filter(x -> (x & 1) == 0).findFirst().orElse(-1));//偶数的第一个数,没找到返回-1
//        intStream.filter(x -> (x & 1) == 0).findFirst().ifPresent((x)-> System.out.println(x));
//        intStream.filter(x -> (x & 1) == 0).findAny().ifPresent((x)-> System.out.println(x));//查找任意一个偶数

//        System.out.println(intStream.allMatch(x -> (x & 1) == 0));//所有都满足
//        System.out.println(intStream.anyMatch(x -> (x & 1) == 0));//任意一个满足
//        System.out.println(intStream.noneMatch(x -> (x & 1) == 0));//所有都不满足
        //endregion

        //region    去重与排序
        Stream stream = Stream.of(1, 1, 2, 2, 3, 3, 3, 4, 5, 6);
//        stream.distinct().forEach(System.out::println);
//        stream
////                .sorted((a, b) -> (int) a < (int) b ? -1 : (int) a == (int) b ? 0 : 1)
////                .sorted((a, b) -> Integer.compare((int) a, (int) b))
////                .sorted(Comparator.comparingInt(o->o.get()))//存对象的list
////                .sorted(Comparator.naturalOrder()) //升序
//                .sorted(Comparator.naturalOrder().reversed().thenComparing(o->o.equals("3")))//降序       多次排序
//                .forEach(System.out::println);

        //endregion

        /**
         * region 化简 reduce      两两合并，只剩一个
         * 使用场景：最大值、最小值、求和、求个数...
         * .reduce((p，x)->r) p 上次的合并结果,x当前元素,r本次合并结果
         * .reduce(init,(p，x)->r) p 上次的合并结果,x当前元素,r本次合并结果
         * .reduce(init,(p，x)->r,(r1,r2)->r) p 上次的合并结果,x当前元素,r本次合并结果
         */
        Stream<Hero> heroStream = Stream.of(
                new Hero("令狐冲", 90),
                new Hero("风清扬", 98),
                new Hero("独孤求败", 100),
                new Hero("方证", 92),
                new Hero("东方不败", 98),
                new Hero("冲虚", 90),
                new Hero("向问天", 88),
                new Hero("任我行", 92),
                new Hero("不戒", 88)
        );

        //1 求最值
//        Optional<Hero> reduce = heroStream.reduce((h1, h2) -> h1.strength > h2.strength ? h1 : h2);  //optional避免流中为空的情况
//        Hero reduce = heroStream.reduce(new Hero("-", -1), (h1, h2) -> h1.strength > h2.strength ? h1 : h2);
//        System.out.println("reduce = " + reduce);
//        System.out.println("max = " + heroStream.max(Comparator.comparingInt(Hero::getStrength)));

        //2 求个数
//        Integer reduce1 = heroStream.map(h -> 1).reduce(0, (a, b) -> a + b);
//        long count = heroStream.count();
//        System.out.println("count = " + count);

        //求和
//        System.out.println("sum = " + heroStream.mapToInt(Hero::getStrength).sum());
        //求平均值
//        System.out.println("avg = " + heroStream.mapToInt(Hero::getStrength).average());
        //endregion


        //region
        //endregion
        //region
        //endregion
        //region
        //endregion
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class Hero {
        private String name;
        private Integer strength;
    }
}
